// RSA, a suite of routines for performing RSA public-key computations in
// JavaScript.
//
// Requires BigInt.js and Barrett.js.
//
// Copyright 1998-2005 David Shapiro.
//
// You may use, re-use, abuse, copy, and modify this code to your liking, but
// please keep this header.
//
// Thanks!
//
// Dave Shapiro
// dave@ohdave.com

function RSAKeyPair(encryptionExponent, decryptionExponent, modulus) {
  this.e = biFromHex(encryptionExponent);
  this.d = biFromHex(decryptionExponent);
  this.m = biFromHex(modulus);
  // We can do two bytes per digit, so
  // chunkSize = 2 * (number of digits in modulus - 1).
  // Since biHighIndex returns the high index, not the number of digits, 1 has
  // already been subtracted.
  this.chunkSize = 2 * biHighIndex(this.m);
  this.radix = 16;
  this.barrett = new BarrettMu(this.m);
}

function twoDigit(n) {
  return (n < 10 ? '0' : '') + String(n);
}

function encryptedString(
  key,
  s // Altered by Rob Saunders (rob@robsaunders.net). New routine pads the // string after it has been converted to an array. This fixes an // incompatibility with Flash MX's ActionScript.
) {
  var a = new Array();
  var sl = s.length;
  var i = 0;
  while (i < sl) {
    a[i] = s.charCodeAt(i);
    i++;
  }

  while (a.length % key.chunkSize !== 0) {
    a[i++] = 0;
  }

  var al = a.length;
  var result = '';
  var j, k, block;
  for (i = 0; i < al; i += key.chunkSize) {
    block = new BigInt();
    j = 0;
    for (k = i; k < i + key.chunkSize; ++j) {
      block.digits[j] = a[k++];
      block.digits[j] += a[k++] << 8;
    }
    var crypt = key.barrett.powMod(block, key.e);
    var text = key.radix === 16 ? biToHex(crypt) : biToString(crypt, key.radix);
    result += text + ' ';
  }
  return result.substring(0, result.length - 1); // Remove last space.
}

function decryptedString(key, s) {
  var blocks = s.split(' ');
  var result = '';
  var i, j, block;
  for (i = 0; i < blocks.length; ++i) {
    var bi;
    if (key.radix === 16) {
      bi = biFromHex(blocks[i]);
    } else {
      bi = biFromString(blocks[i], key.radix);
    }
    block = key.barrett.powMod(bi, key.d);
    for (j = 0; j <= biHighIndex(block); ++j) {
      result += String.fromCharCode(
        block.digits[j] & 255,
        block.digits[j] >> 8
      );
    }
  }
  // Remove trailing null, if any.
  if (result.charCodeAt(result.length - 1) === 0) {
    result = result.substring(0, result.length - 1);
  }
  return result;
}
